// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree.

package collider

import (
	"errors"
	"io"
	"log"
	"time"
)

const maxQueuedMsgCount = 1024

// client 代表一个客户端实例。
type client struct {
	id string
	// rwc 是用于访问 WebSocket 连接的接口。
	// 它在客户端向服务器注册后被设置。
	rwc io.ReadWriteCloser
	// msgs 是从此客户端发送的、已排队的消息。
	msgs []string
	// timer 用于在客户端超时未注册时将其移除。
	timer *time.Timer
}

// newClient 创建一个新的客户端实例。
func newClient(id string, t *time.Timer) *client {
	log.Printf(">>> 创建新客户端: id=%s", id)
	c := client{id: id, timer: t}
	return &c
}

// setTimer 设置客户端的定时器。
func (c *client) setTimer(t *time.Timer) {
	if c.timer != nil {
		c.timer.Stop()
	}
	c.timer = t
}

// register 如果尚未完成，则将 ReadWriteCloser 绑定到客户端。
func (c *client) register(rwc io.ReadWriteCloser) error {
	if c.rwc != nil {
		log.Printf("!!! 注册失败: 客户端 %s 已有连接", c.id)
		return errors.New("重复注册")
	}
	log.Printf(">>> 客户端 %s 正在绑定连接...", c.id)
	c.setTimer(nil)
	c.rwc = rwc
	return nil
}

// deregister 如果存在，则关闭 ReadWriteCloser。
func (c *client) deregister() {
	if c.rwc != nil {
		log.Printf(">>> 注销客户端 %s 的连接", c.id)
		c.rwc.Close()
		c.rwc = nil
	}
}

// registered 返回客户端是否已注册。
func (c *client) registered() bool {
	return c.rwc != nil
}

// enqueue 将一条消息添加到客户端的消息队列中。
func (c *client) enqueue(msg string) error {
	if len(c.msgs) >= maxQueuedMsgCount {
		log.Printf("!!! 入队失败: 客户端 %s 的消息队列已满", c.id)
		return errors.New("客户端排队的消息过多")
	}
	log.Printf(">>> 客户端 %s 的消息已入队", c.id)
	c.msgs = append(c.msgs, msg)
	return nil
}

// sendQueued 将排队的消息发送给另一个客户端。
func (c *client) sendQueued(other *client) error {
	if other == nil || c.id == other.id || other.rwc == nil {
		log.Printf("!!! 发送排队消息失败: 无效的接收方客户端。发送方: %s, 接收方: %v", c.id, other)
		return errors.New("无效的客户端")
	}
	if len(c.msgs) == 0 {
		return nil
	}

	log.Printf(">>> 正在从 %s 发送 %d 条排队消息到 %s", c.id, len(c.msgs), other.id)
	for _, m := range c.msgs {
		if err := sendServerMsg(other.rwc, m); err != nil {
			log.Printf("!!! 发送排队消息时出错: %v", err)
			return err
		}
	}
	c.msgs = nil
	log.Printf(">>> 从 %s 到 %s 的排队消息发送完毕", c.id, other.id)
	return nil
}

// send 如果另一个客户端已注册，则将消息发送给它，否则将消息排队。
func (c *client) send(other *client, msg string) error {
	if other == nil || c.id == other.id {
		log.Printf("!!! 发送消息失败: 无效的接收方客户端。发送方: %s, 接收方: %v", c.id, other)
		return errors.New("无效的客户端")
	}
	if other.rwc != nil {
		return sendServerMsg(other.rwc, msg)
	}
	return c.enqueue(msg)
}
